--机器人逻辑基类

local skynet = require "skynet"
local filelog = require"filelog"
local tabletool = require "tabletool"
local base = require "base"
require "pubenum"

--
--准备延时时间权值表
--
local ready_delay_weights = {
    [1] = 15,   --1s
    [2] = 35,   --2s
    [3] = 30,   --3s
    [4] = 15,   --4s
    [4.5] = 5,  --5s
}

--
--doaction延时时间权值表
--
local doaction_delay_weights = {
    [1] = 20,   --1s
    [2] = 30,   --2s
    [3] = 30,   --3s
    [4] = 10,   --4s
    [5] = 5,    --5s
    [6] = 5,    --6s
}

---------

local RobotBaseLogic = { 
    _ready_delay = ready_delay_weights,
    _doaction_delay = doaction_delay_weights,
}

----------------------------------
--辅助函数

--
--计算总权值
--
local function calculate_total_weight(w_list)
    local total_weight = 0
    for id,w in pairs(w_list) do
        total_weight = total_weight + w
    end

    return total_weight
end

--根据权值表，获取随机结果
local function get_random_result_by_weightlist(weight_list, total_w)
    total_w = total_w or calculate_total_weight(weight_list)
    local r = base.get_random(1,total_w)
    local sum = 0
    for id,w in pairs(weight_list) do
        sum = sum + w
        if r <= sum then
            return id
        end
    end
    return   
end

---------------------

--[Comment]
--创建一个新逻辑对象
--
function RobotBaseLogic:new(obj)
    obj = obj or {}
    setmetatable(obj, self)
    self.__index = self
    obj._super = self
    return obj
end

--[Comment]
--延迟ns
--机器人执行一个动作前，做一定延迟
--默认延时1~3s
--arg 为number时表示延时的秒数，为table时表示根据一个权值表随机延时
--
function RobotBaseLogic:delay(arg)
    local argtype = type(arg)
    if argtype == "number" then
        skynet.sleep( math.floor(arg * 100))
    elseif argtype == "table" then
        local tm = get_random_result_by_weightlist(arg,100)
        skynet.sleep( math.floor(tm * 100))
    elseif argtype == "string" then
        local tm = 0
        local name = "_" .. arg .. "_delay"
        if self[name] then
            tm = get_random_result_by_weightlist(self[name],100)
        else
            tm = base.get_random(1,3)
        end
        skynet.sleep( math.floor(tm * 100))
    else
        skynet.sleep(base.get_random(1,3) * 100)
    end
end

--[Comment]
--调用父类的同名方法
--
function RobotBaseLogic:super(msghead, msgbody, funcname)
    if not funcname and msghead then
       funcname = msghead.retstr or "_"
    end
    funcname = funcname or "_"
    
    local func = self._super[funcname]
    if func then
        return func(self, msghead, msgbody)
    end
end

-----------------

--[Comment]
-- 对服务器发来的消息统一处理
-- 服务器返回错误，则不再处理该消息
--
function RobotBaseLogic:process(session, source, msghead, msgbody)
    if msghead.retcode and tonumber(msghead.retcode) ~= 0 then
        if msghead.msgname == "entergameR" and msghead.retcode == -99 then
            skynet.sleep(100)
            self.service:login()
        end
        filelog.sys_error("---- RobotBaseLogic.proccess msg ret error ----",msghead, msgbody)
        return
    end

    local nodetype = "gate"
    local msgname = msghead.msgname
    local dotbegin, dotend = string.find(msghead.msgname, '.', 1, true)
	if dotbegin and dotbegin > 0 then
		nodetype = string.sub(msghead.msgname,1, dotbegin - 1)
        msgname = string.sub(msghead.msgname, dotend + 1)
	end

    local func = self[msgname]
    if func then
        msghead.retstr = msgname
        local status,result = skynet.pcall(func, self, msghead, msgbody, nodetype)
        if not status then
            filelog.sys_error("----RobotBaseLogic:process call function failed! funcname:", msgname, status, result)
        end
        return result
    else
        --filelog.sys_info("---- RobotBaseLogic.proccess recv no handler msg ----",msghead, msgbody)
    end
end

--[Comment]
-- 检测机器人是否离桌
-- 由调度服务发起, 可以离桌返回true
--
function RobotBaseLogic:check_leavetable()
    --什么也不做
end

----------------------------------------------------

--[Comment]
-- 处理entertableR消息
--
function RobotBaseLogic:entertableR(msghead, msgbody, nodetype)
    self.service.gamenode = self.service.target_game
    self.service.table_index = self.service.target_table
    self.service:sitdowntable()
end

--[Comment]
-- 处理reentertableR消息
--
function RobotBaseLogic:reentertableR(msghead, msgbody)
    self.service.state = 2 --游戏中
    self.service.start_matchtime = 0
    self.service.gamenode = self.service.target_game
    self.service.table_index = self.service.target_table
    local tabletype = self.service:get_tabletype()
    skynet.send(".schedulemgr", "lua", "update_schedule_task", self.service.schedule_id, self.service.rid, self.service.gamenode, tabletype)
end

--[Comment]
-- 处理sitdowntableN消息
--
function RobotBaseLogic:sitdowntableN(msghead, msgbody)
    local respmsg = tabletool.deepcopy(msgbody)
    local is_self = false
    for k,v in pairs(respmsg) do
        if k == "rid" and v == self.service.rid then
            is_self = true
            break
        elseif type(v) == "table" and v.rid == self.service.rid then
             is_self = true
            break
        end
    end
    
    if is_self then
        self.service.state = 2 --游戏中
        if self.service.schedule_id then    --更新调度任务
            local tabletype = self.service:get_tabletype()
            skynet.send(".schedulemgr", "lua", "update_schedule_task", self.service.schedule_id, self.service.rid, self.service.gamenode, tabletype)
            self.service.schedule_id = nil
        end
    end
end

--[Comment]
-- 处理doreadyN消息
--
function RobotBaseLogic:doreadyN(msghead, msgbody)
    local body = tabletool.deepcopy(msgbody)
    if not body.rid or body.rid == self.service.rid then
        if self.service.target_state == 1 then
            self.service:leavetable()
        elseif self.service.target_game and self.service.target_table then
            self.service:gameready()
        end
    end
end

--[Comment]
-- 处理leavetableN消息
--
function RobotBaseLogic:leavetableN(msghead, msgbody)
    if msgbody.rid == self.service.rid then
        local gamenode = self.service.gamenode
        self.service.state = 1
        self.service.gamenode = nil
        self.service.table_index = nil
        self.service:reset_gameinfo()
        if self.service.target_match and self.service.start_matchtime > 0 then
            return
        end
        self.service:agentexit(true,gamenode)
    end
end

--[Comment]
-- 处理matchresultN消息
--
function RobotBaseLogic:matchresultN(msghead, msgbody, nodetype)
    self.service.start_matchtime = 0
    self.service:reentertable(msgbody.table_index, nodetype)
end

--[Comment]
-- 处理restartmatchN消息
--
function RobotBaseLogic:restartmatchN(msghead, msgbody)
    if self.service.target_match and self.service.target_level then
        self.service:entermatchtable(msgbody.match_type, msgbody.nodename)
    end
end

--[Comment]
-- 处理coinmatchresultN消息
--
function RobotBaseLogic:coinmatchresultN(msghead, msgbody, nodetype)
    self.service.start_matchtime = 0
    self.service:reentertable(msgbody.table_index, nodetype)
end

--[Comment]
-- 处理restartcoinmatchN消息
--
function RobotBaseLogic:restartcoinmatchN(msghead, msgbody)
    if self.service.target_match and self.service.target_level then
        self.service:entercoinmatchtable(msgbody.match_type, msgbody.nodename)
    end
end

--[Comment]
-- 处理entermatchtableR消息
--
function RobotBaseLogic:entermatchtableR(msghead, msgbody)
    --更新调度任务
    skynet.send(".schedulemgr", "lua", "update_schedule_task", self.service.schedule_id, self.service.rid, self.service.target_game, "diamond", true)
    self.service.schedule_id = nil
end

--[Comment]
-- 处理entercoinmatchtableR消息
--
function RobotBaseLogic:entercoinmatchtableR(msghead, msgbody)
    --更新调度任务
    skynet.send(".schedulemgr", "lua", "update_schedule_task", self.service.schedule_id, self.service.rid, self.service.target_game, "coin", true)
    self.service.schedule_id  = nil
end

--[Comment]
-- 处理cancelmatchR消息
--
function RobotBaseLogic:cancelmatchR(msghead, msgbody)
    if self.service.start_matchtime ~= 0 then
        self.service.target_game = nil
        self.service.target_level = nil
        self.service:agentexit(true)
    end
end

--[Comment]
-- 处理cancelcoinmatchR消息
--
function RobotBaseLogic:cancelcoinmatchR(msghead, msgbody)
    if self.service.start_matchtime ~= 0 then
        self.service.target_game = nil
        self.service.target_level = nil
        self.service:agentexit(true)
    end
end

----------------------------------
--以下消息不做任何处理

--[Comment]
-- 处理sitdowntableR消息
--
function RobotBaseLogic:sitdowntableR(msghead, msgbody)
    
end

--[Comment]
-- 处理gamereadyR消息
--
function RobotBaseLogic:gamereadyR(msghead, msgbody)
    
end

--[Comment]
-- 处理leavetableR消息
--
function RobotBaseLogic:leavetableR(msghead, msgbody)
    
end

--[Comment]
-- 处理doactionR消息
--
function RobotBaseLogic:doactionR(msghead, msgbody)
    
end

--[Comment]
-- 处理standuptableN消息
--
function RobotBaseLogic:standuptableN(msghead, msgbody)

end

--[Comment]
-- 处理gamereadyN消息
--
function RobotBaseLogic:gamereadyN(msghead, msgbody)
    
end

--[Comment]
-- 处理doactionN消息
--
function RobotBaseLogic:doactionN(msghead, msgbody)
    
end

--[Comment]
-- 处理todoN消息
--
function RobotBaseLogic:todoN(msghead, msgbody)
    
end

-------------------------------------------------------
-------------------------------------------------------
--大厅消息

--[Comment]
-- 处理authR消息
--
function RobotBaseLogic:authR(msghead, msgbody)
    self.service:entergame(msgbody)
end

--[Comment]
-- 处理entergameR消息
--
function RobotBaseLogic:entergameR(msghead, msgbody)
    local service = self.service
    if msgbody.isreauth == 1 then
        service:login()
    else
        service.state = 1
        service.servertime = msgbody.servertime
        service.gamenode = msgbody.gamenode
        service.table_index = msgbody.table_index or 0
        if service.table_index <= 0 then
            service.table_index = nil
        end
        service.match_gamenode = msgbody.match_gamenode
        service.match_tabletype = msgbody.match_tabletype
        service:updateinfo(msgbody.baseinfo,true)
        local status = service:changeinfo()
        if not status then  --没钱直接退出
            return service:agentexit(true)
        end
        if service.target_state == 2 then
            if service.target_table then
                service:entertable()
            elseif service.target_match == "diamond" then
                service:entermatchtable()
            elseif service.target_match == "coin" then
                service:entercoinmatchtable()
            end
        end
    end
end

--[Comment]
-- 处理heartR消息
--
function RobotBaseLogic:heartR(msghead, msgbody)
    self.service.servertime = msgbody.servertime
end

--[Comment]
-- 处理getroleinfoR消息
--
function RobotBaseLogic:getroleinfoR(msghead, msgbody)
    self.service:updateinfo(msgbody.baseinfo,true)
end

--[Comment]
-- 处理changemoneyN消息
--
function RobotBaseLogic:changemoneyN(msghead, msgbody)
    self.service:updatemoney(msgbody.rolemoney)
end

--[Comment]
-- 处理changebaseinfoN消息
--
function RobotBaseLogic:changebaseinfoN(msghead, msgbody)
    self.service:updateinfo(msgbody.baseinfo)
end

----------------------------
--以下消息，不做任何处理

--[Comment]
-- 处理updateroleinfoR消息
--
function RobotBaseLogic:updateroleinfoR(msghead, msgbody)
    
end

--[Comment]
-- 处理gettablebycodeR消息
--
function RobotBaseLogic:gettablebycodeR(msghead, msgbody)
    
end

--[Comment]
-- 处理getpubtablelistR消息
--
function RobotBaseLogic:getpubtablelistR(msghead, msgbody)
    
end

--[Comment]
-- 处理getcoinpubtablelistR消息
--
function RobotBaseLogic:getcoinpubtablelistR(msghead, msgbody)
    
end

--[Comment]
-- 处理usepropR消息
--
function RobotBaseLogic:usepropR(msghead, msgbody)
    
end

--[Comment]
-- 处理tablechatR消息
--
function RobotBaseLogic:tablechatR(msghead, msgbody)
    
end

--[Comment]
-- 处理kickroleN消息
--
function RobotBaseLogic:kickroleN(msghead, msgbody)
    
end

--[Comment]
-- 处理tablechatN消息
--
function RobotBaseLogic:tablechatN(msghead, msgbody)
    
end

return RobotBaseLogic
